//////////////////////////////////////////////////////////////////////////
//
// GAM203
// Shader Manager
// ShaderMgr.cpp
// 
// Scott Taylor
// Qantm College
//
//////////////////////////////////////////////////////////////////////////

#include "ShaderMgr.h"
#include "Shader.h"

#include <stdio.h>
#include <assert.h>

// Singleton instance
ShaderMgr* Singleton<ShaderMgr>::m_pInstance = NULL;

//
// Default constructor
//
ShaderMgr::ShaderMgr()
{
}

//
// Destructor
//
ShaderMgr::~ShaderMgr()
{
	Shutdown();
}

//
// Cleans up after class, unloads all shaders
//
void ShaderMgr::Shutdown()
{
	// Delete all loaded shaders
	// Note: We do not need to individually erase() the shaders from the list because
	//       the list is being clear()ed afterwards
	for (ShaderList::iterator iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
	{
		Shader* pElem = *iter;
		if (pElem)
		{
			// No need to call Release() on this class because it is our own!
			// (It will internally release the DirectX stuff in its d'tor)
			delete pElem;
		}
	}
	m_shaders.clear();
}

//
// Loads a shader from file, registers it with manager
// Returns true if successful
//
bool ShaderMgr::Load(IDirect3DDevice9* a_pDevice, const char* a_pName, const char* a_pEffectFilename)
{
	assert(a_pName && a_pName[0] && a_pEffectFilename && a_pEffectFilename[0]);
	if (!(a_pName && a_pName[0] && a_pEffectFilename && a_pEffectFilename[0]))
	{
		// Bad input parameters
		return false;
	}

	Shader* pNewShader = new Shader(a_pName);
	bool isLoaded = pNewShader->Load(a_pDevice, a_pEffectFilename);
	if (!isLoaded)
	{
		// Failed to load shader; it should have logged some error output (from a compile error)
		// You can see the output in Debug > Windows > Output
		// Since we failed, just clean up (and don't add the shader to our list)
		delete pNewShader;
		return false;
	}

	// Shader successfully loaded! Store it in our list
	m_shaders.push_back(pNewShader);

	return true;
}

//
// Finds a shader by name; the shader must have been previously loaded via Load()
// Returns NULL if not found
//
Shader* ShaderMgr::Find(const char* a_pName)
{
	assert(a_pName);
	if (a_pName)
	{
		for (ShaderList::iterator iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
		{
			Shader* pElem = *iter;

			// Note: This is a SLOW (DODGY) string compare!
			//       Normally we would use an ID or string hash... but this is simpler for us for now
			if (strcmp(pElem->GetName(), a_pName) == 0)
			{
				// Found the shader!
				return pElem;
			}
		}
	}

	// Failed to find shader
	return NULL;
}

